Declarative এবং Procedural Macros এর ব্যবহার

Macros (ম্যাক্রোস) - রাস্ট (Rust) - Computer Programming

212

Rust-এ macros হল কোডের একটি শক্তিশালী বৈশিষ্ট্য যা কোডের পুনঃব্যবহারযোগ্যতা এবং অ্যাবস্ট্রাকশন উন্নত করতে সাহায্য করে। ম্যাক্রো একটি কোড তৈরির পদ্ধতি যা একটি নির্দিষ্ট প্যাটার্ন বা টেমপ্লেটের মাধ্যমে কমপাইল টাইমে কোড প্রসেসিং করে। Rust-এ দুটি প্রধান ধরনের ম্যাক্রো রয়েছে: Declarative Macros এবং Procedural Macros


Declarative Macros

Declarative macros হল Rust-এর ম্যাক্রোর একটি সাধারণ এবং প্রচলিত ধরন, যা macro_rules! কীওয়ার্ড দিয়ে ডিফাইন করা হয়। এই ম্যাক্রো সাধারণত কোডের টেমপ্লেট তৈরি করে, এবং আপনার নির্দিষ্ট প্যাটার্নের ভিত্তিতে একাধিক সিমিলার কোড তৈরি করতে পারে।

Declarative Macros এর বৈশিষ্ট্য:

  • সাধারণত সহজ এবং দ্রুত ব্যবহারের জন্য ডিজাইন করা হয়।
  • নির্দিষ্ট প্যাটার্নের ভিত্তিতে কোড তৈরি করতে ব্যবহৃত হয়।
  • macro_rules! দিয়ে ডিফাইন করা হয়।

উদাহরণ: Declarative Macro

// macro_rules! দিয়ে একটি simple macro তৈরি
macro_rules! say_hello {
    () => {
        println!("Hello, World!");
    };
}

fn main() {
    // মেক্রো কল করা
    say_hello!();  // আউটপুট: Hello, World!
}

এখানে, say_hello! একটি declarative macro যা কোনো আর্গুমেন্ট না নিয়েই "Hello, World!" প্রিন্ট করবে। macro_rules! দিয়ে এটি ডিফাইন করা হয়েছে এবং এই ম্যাক্রো একটি নির্দিষ্ট টেমপ্লেটের মতো কাজ করছে।

প্যাটার্ন মেলানো:

Declarative macros-এ আপনি বিভিন্ন প্যাটার্ন ব্যবহার করে কোড জেনারেট করতে পারেন।

macro_rules! create_point {
    // (x, y) প্যাটার্নে কোড তৈরি
    ($x:expr, $y:expr) => {
        println!("Point: ({}, {})", $x, $y);
    };
}

fn main() {
    create_point!(10, 20);  // আউটপুট: Point: (10, 20)
}

এখানে create_point! ম্যাক্রো দুটি এক্সপ্রেশন নিল এবং সেগুলিকে কোডে একত্রিত করে একটি পয়েন্ট প্রিন্ট করেছে।


Procedural Macros

Procedural macros হল আরও শক্তিশালী এবং জটিল ম্যাক্রো, যা function-like টেমপ্লেটের মাধ্যমে কাজ করে। এই ম্যাক্রোগুলির মাধ্যমে আপনি কোডের উপর আরও নিয়ন্ত্রণ পেতে পারেন এবং সাধারণত বড় প্রোজেক্টে বা রিফ্লেকশন/মেটা-প্রোগ্রামিংয়ের জন্য ব্যবহৃত হয়।

Procedural macros এ, Rust কম্পাইলার TokenStream দিয়ে ইনপুট নেয় এবং আউটপুট হিসেবে একটি নতুন TokenStream প্রদান করে। Procedural macros সাধারণত দুটি অংশে বিভক্ত:

  1. Derive Macros
  2. Attribute-like Macros
  3. Function-like Macros

Procedural Macros এর বৈশিষ্ট্য:

  • কমপাইল টাইমে কাজ করে, এবং কোড জেনারেট করতে আরও বেশি নিয়ন্ত্রণ দেয়।
  • সাধারণত একটি আলাদা crate (library) হিসেবে ডিফাইন করতে হয়।

উদাহরণ: Derive Procedural Macro

derive ম্যাক্রো Rust-এর একটি বিশেষ ধরনের procedural macro যা স্ট্রাকচার বা enum-এর উপর কোনো ট্রেইট ইমপ্লিমেন্টেশন জেনারেট করতে ব্যবহৃত হয়।

// Procedural Macro Crate প্রয়োজন
// `#[derive(Debug)]` এর মাধ্যমে স্ট্রাকচার প্রিন্ট করা সম্ভব
#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let person = Person {
        name: String::from("Alice"),
        age: 30,
    };
    // Debug ম্যাক্রো ব্যবহার করে আউটপুট প্রিন্ট
    println!("{:?}", person);  // আউটপুট: Person { name: "Alice", age: 30 }
}

এখানে, #[derive(Debug)] এর মাধ্যমে একটি স্ট্রাকচার Debug ট্রেইট ইমপ্লিমেন্ট করা হয়েছে, যা সহজেই প্রিন্টযোগ্য করে তোলে।

উদাহরণ: Attribute-like Procedural Macro

// 'hello_world' নামে একটি attribute procedural macro
use proc_macro::TokenStream;

#[proc_macro]
pub fn hello_world(_input: TokenStream) -> TokenStream {
    "fn hello() { println!(\"Hello, World!\"); }".parse().unwrap()
}

fn main() {
    hello_world!();  // আউটপুট: "Hello, World!"
}

এখানে, hello_world! একটি attribute-like procedural macro যা একটি ফাংশন তৈরি করে এবং তাকে প্রিন্ট করতে বলে।


Procedural Macros তৈরি করা

Procedural macros সাধারণত একটি পৃথক crate এ তৈরি হয়, যেটি Rust প্রোজেক্টে proc-macro ফিচার ব্যবহার করে ডিফাইন করা হয়।

উদাহরণ: Procedural Macro Crate

Cargo.toml-এ proc-macro ফিচারটি যোগ করতে হবে:

[lib]
proc-macro = true

এরপর, একটি procedural macro তৈরি করা যেতে পারে। উদাহরণস্বরূপ:

use proc_macro::TokenStream;

#[proc_macro]
pub fn hello_world(_input: TokenStream) -> TokenStream {
    "fn hello() { println!(\"Hello, World!\"); }".parse().unwrap()
}

এটি hello_world! নামে একটি ম্যাক্রো তৈরি করে, যা একটি ফাংশন প্রিন্ট করতে ব্যবহার করা হবে।


সারাংশ

Rust-এ macros একটি শক্তিশালী বৈশিষ্ট্য, যা কোড পুনঃব্যবহার এবং অ্যাবস্ট্রাকশন সহজ করে তোলে। Declarative macros সাধারণত সহজ এবং প্রেডিকটেবল, যা macro_rules! দিয়ে ডিফাইন করা হয়। অন্যদিকে, Procedural macros আরও শক্তিশালী এবং জটিল, যা কমপাইল টাইমে কোড প্রসেসিং এবং জেনারেশন করতে সক্ষম। Procedural macros সাধারণত ডেভেলপারদের জন্য বেশি নিয়ন্ত্রণ দেয় এবং এটি derive, attribute-like, এবং function-like ফর্মে ব্যবহৃত হয়।

Content added By
Promotion

Are you sure to start over?

Loading...